/**
 * sukai
 * 机器臂驱动
 * 2020/12/21
 */
#include "IIMTDriver.h"

//shared_ptr<IIMTDriver> IIMTDriver::instance = shared_ptr<IIMTDriver>(new IIMTDriver);

mutex *IIMTDriver::m = new mutex;
IIMTDriver *IIMTDriver::instance = nullptr;
IIMTDriver::IIMTDriver(QWidget *parent): QWidget(parent) {
    qDebug() << "QTcpSocket客户端已启动";
    //监听connected信号
    QObject::connect(&socket, &QTcpSocket::connected, [this] {
        connectCallBack();

        qDebug() << "QTcpSocket 已链接";
        //解析数据
       // readMessage();
    });

    //断开连接信号
    QObject::connect(&socket, &QTcpSocket::disconnected, [this] {
        disConnectCallBack();
        qDebug() << "QTcpSocket robot端已断开";
    });
    //139个字段, 1108个字节解析成139个字段,用结构体 data.h保存
    QObject::connect(&socket, &QTcpSocket::readyRead, [this] {

                 // (int)sizeof (qint64);
                // socket.bytesAvailable();
                qDebug() << "===========IIMTDriver 29行解析返回的数据 socket.bytesAvailable(): ==========="<<  socket.bytesAvailable();
                 qDebug() << "===========&socket, &QTcpSocket::readyRead: ==========="<<  socket.bytesAvailable();
                //300ms 内收不到数据
                socket.waitForReadyRead(300);
                QCoreApplication::processEvents();//这个函数的意思就是让调用此函数的线程执行其消息队列中的事件，直至没有事件可以执行为止
                QByteArray data = socket.readAll();
                 QString msgba = QString(data);

//                while (socket.bytesAvailable()>0&& socket.bytesAvailable()<data.size()) {
//                    if(socket.bytesAvailable()>0){
//                        qDebug() << "===========while (socket.bytesAvailable()<data.size()) ==========="<<  socket.bytesAvailable();
//                        QByteArray data1 = socket.readAll();

//                        QString msgba1 = QString(data1);
//                        qDebug() << " ***********************while (socket.bytesAvailable()<data.size())**************************************: "<< msgba1;

//                    }


//                }

                //注释掉直接解析Json函数，原因是直接解析速度太慢，容易出现粘包现象|启用队列执行解析Json
               // parseJson(msgba);
               //数据加入队列
               instructionMessageQueue.push(msgba);


         //qDebug() << "IIMTDriver 29行解析返回的数据msgba: "<< msgba;
        //iimtData.h结构体用来保存数据
        // IIMT_Data iimtData;
        //解析返回的数据
     //   parseData(data, iimtData);
        //决定是否执行下一条指令
      //  decideExcuteNextInstruction(iimtData);
    });
//==============================================================
    timer.setInterval(300);
     timer.start();
        //数据接收
       QObject::connect(&timer, &QTimer::timeout,this , &IIMTDriver::managemsg);
    //管理接收到的数据


}


//管理数据
void IIMTDriver::managemsg(){
    try {

       // std::cout<<"sukai QTimer IIMTDriver 管理数据 managemsg " <<std::endl;


        if(instructionMessageQueue.empty() )
            return;



       std::cout<<"sukai QTimer::timeout =IIMTDriver=====managemsg====instructionMessageQueue.size()================== " <<instructionMessageQueue.size()<<std::endl;

          //1.取出一条指令
          QString msgba = instructionMessageQueue.front();
          qDebug() << "IIMTDriver 99行解析返回的数据instructionMessageQueue msgba: "<< msgba;
          //2.解析Json
          parseJson(msgba);
          //3.删出处理过的数据
          instructionMessageQueue.pop();

    }catch (std::exception e){
        e.what();
        std::cout<<"QTcpServer 数据发送给所有客户端: " <<e.what()<<std::endl;
    }

}



IIMTDriver::~IIMTDriver() {
    cout << "析构函数" << endl;
    socket.close();
}

//shared_ptr<IIMTDriver> IIMTDriver::getInstance() {
//    return instance;
//}

void IIMTDriver::connectToRobot(QString ip, int port) {
    socket.connectToHost(ip, port);
     cout << "IIMTDriver::connectToRobot(ip, port) 连接无人车 " << endl;
}

//连接无人车
void IIMTDriver::setConnectCallBack(function<void()> connectCallBack) {
    this->connectCallBack = connectCallBack;
}

//断开无人车
void IIMTDriver::setDisConnectCallBack(function<void()> disConnectCallBack) {
    this->disConnectCallBack = disConnectCallBack;
}



//-----------------传到函数传到ui去------------------------




//sukai 路点数据 传到函数传到ui去
void IIMTDriver::setTestInfos_listCallBack(function<void(QList<TestInfo> testInfos)> maptestInfos_list_CallBack1){
    this->maptestInfos_list_CallBack = maptestInfos_list_CallBack1;
}
//sukai 字典数据 传到函数传到ui去
void IIMTDriver::setDictionarie_listCallBack(function<void(QList<Dictionaries> dictionaries_s)> mapdictionarie_list_CallBack1){
    this->mapdictionarie_list_CallBack = mapdictionarie_list_CallBack1;
}
//sukai 执行路点任务 传到函数传到ui去
void IIMTDriver::setTaskPOSECallBack(function<void(QList<TaskPOSE> taskPOSEs)> maptaskPOSEMaps_list_CallBack1){
    this->maptaskPOSEMaps_list_CallBack = maptaskPOSEMaps_list_CallBack1;
}
//sukai 定时任务 传到函数传到ui去
void IIMTDriver::setTime_taskCallBack(function<void(QList<Table_Task> Time_Tasks)> mapTable_time_task_list_CallBack1){
    this->mapTable_time_task_list_CallBack = mapTable_time_task_list_CallBack1;
}
//sukai 获取地图名称
void IIMTDriver::setMapNames_listCallBack(function<void(QList<QMap<QString,std::vector<std::string>>> mapNames_list)> mapNames_list_CallBack1){
    this->mapNames_list_CallBack = mapNames_list_CallBack1;
}
//sukai 到达点位后返回的数据
void IIMTDriver::setArriveRobotCallBack(function<void(ArriveRobot arriveRobot)> arriveRobot_CallBack1){
    this->arriveRobot_CallBack = arriveRobot_CallBack1;
}
//sukai 机器人的一些基本信息
void IIMTDriver::setRobot_infoCallBack(function<void(Robot_info robot_info)> robot_info_CallBack1){
    this->robot_info_CallBack = robot_info_CallBack1;
}
//sukai 小车的运行状态
void IIMTDriver::setRobot_statusCallBack(function<void(QString robot_status)> robot_status_CallBack1){
    this->robot_status_CallBack = robot_status_CallBack1;
}
//sukai 保存地图后反馈
void IIMTDriver::setRobot_saveGmappingMap_CallBack(function<void(SaveGmappingMap saveGmappingMap)> robot_saveGmappingMap_CallBack1){
    this->robot_saveGmappingMap_CallBack = robot_saveGmappingMap_CallBack1;
}

//sukai 获取所有运行的node节点的名称 传到函数传到ui去
void IIMTDriver::setNodeName_listCallBack(function<void(QList<QString> nodeName_list)> nodeName_listCallBack1){
    this->nodeName_listCallBack = nodeName_listCallBack1;
}
//sukai 收到的所有数据 传到函数传到ui去
void IIMTDriver::setMsgba_CallBack(function<void(QString msgba)> msgba_CallBack1){
   this->msgba_CallBack = msgba_CallBack1;
}


//------------------传到编辑类------------------------

 // todo sukai 2022-01-22  接收授权码服务验证结果
 void IIMTDriver::setRegisterServiceResult_CallBack(function<void(QString registerServiceResult)> registerServiceResult_CallBack1){
     this->registerServiceResult_CallBack = registerServiceResult_CallBack1;
 }

//sukai 路点数据 传到编辑类 KSDemoDlg 中                                  QList<QMap<QString, QString>> maptestInfos_list;
void IIMTDriver::setKSDemoDlg_testInfos_listlistCallBack(function<void(QList<QMap<QString, QString> > kSDemoDlg_testInfos_list)> kSDemoDlg_testInfos_list_CallBack1){
    this->kSDemoDlg_testInfos_list_CallBack = kSDemoDlg_testInfos_list_CallBack1;
}
//sukai 字典数据 传到编辑类 KSDemoDlgtaskparamer 中
void IIMTDriver::setKSDemoDlg_dictionarie_listCallBack(function<void(QList<QMap<QString, QString> > kSDemoDlg_dictionarie_list)> kSDemoDlg_dictionarie_list_CallBack1){
    this->kSDemoDlg_dictionarie_list_CallBack = kSDemoDlg_dictionarie_list_CallBack1;
}
//sukai 执行路点任务 传到编辑类 KSDemoDlgtask 中
void IIMTDriver::setKSDemoDlg_task_poseCallBack(function<void(QList<QMap<QString, QString> > kSDemoDlg_task_pose_list)> kSDemoDlg_task_pose_list_CallBack1){
    this->kSDemoDlg_task_pose_list_CallBack = kSDemoDlg_task_pose_list_CallBack1;
}
//sukai 定时任务 传到编辑类 KSDemoDlgtaskTime 中
void IIMTDriver::setKSDemoDlg_task_timeCallBack(function<void(QList<QMap<QString, QString> > kSDemoDlg_task_time_list)> kSDemoDlg_task_time_list_CallBack1){
    this->kSDemoDlg_task_time_list_CallBack = kSDemoDlg_task_time_list_CallBack1;
}

//sukai 虚拟墙 传到编辑类 KSDemoDlgtaskTime 中
void IIMTDriver::setKSDemoDlg_task_costmapLayerCallBack(function<void(QList<QMap<QString, QString> > kSDemoDlg_task_costmapLayer_list_CallBack)> kSDemoDlg_task_costmapLayer_list_CallBack1){
     this->kSDemoDlg_task_costmapLayer_list_CallBack = kSDemoDlg_task_costmapLayer_list_CallBack1;
}


//---------------------------------------------------




//发送数据给无人车
void IIMTDriver::sendMsg(QString msg){

  //  QString info= socket.peerAddress().toString()+":"+QString("%1").arg( socket.peerPort());
    //发送指令
    qDebug()<<"IIMTDriver::sendMsg 发送指令 "<<msg;
    socket.write(msg.toUtf8());
    socket.flush();
  //  qDebug()<<"IIMTDriver::sendMsg 发送指令";
}
//=============================================================================
//解析Json
void  IIMTDriver::parseJson(QString &msgba){

    //sukai 收到的所有数据 传到函数传到ui去
    if(msgba_CallBack!=nullptr){
        msgba_CallBack(msgba);
     //   qDebug()<<"=============msgba================== ";
    }
   //  qDebug()<<"msgba: "<<msgba;
    QJsonParseError parseJsonErr;
    QJsonDocument document = QJsonDocument::fromJson(msgba.toUtf8(),&parseJsonErr);
    if(!(parseJsonErr.error == QJsonParseError::NoError))
    {

        qDebug()<<"========================解析json文件错误！========================";
        qDebug()<<"========================解析json文件错误！========================";
        qDebug()<<"========================解析json文件错误！========================";
        qDebug()<<"========================解析json文件错误！========================";
        qDebug()<<"========================解析json文件错误！========================";
        qDebug()<<"========================解析json文件错误！========================";
        if(robot_status_CallBack!=nullptr){
          robot_status_CallBack("暂时解析json文件错误，原因粘包，即将执行针对性解包！");
        }
        QList<QString> jsonlist;
        //如果存在粘包就这么处理，2个或多个json肯定存在 }{ 这种类型
        if(msgba.contains("}{")){
           QStringList msglist0 = msgba.split("}{");
           for (int i = 0; i <msglist0.size() ; ++i) {
               if(i==0){//第一个
                QString msgjson=msglist0[i]+"}";
                qDebug()<<"====1==解析json文件错误 针对性解包=======msgjson==================: "<<msgjson;
               jsonlist.push_back(msgjson);
              }else if(i<(msglist0.size()-1)){
                   QString msgjson="{"+msglist0[i]+"}";
                   qDebug()<<"===2===解析json文件错误 针对性解包=======msgjson==================: "<<msgjson;

                   jsonlist.push_back(msgjson);
               }else if(i==(msglist0.size()-1)){//最后一个
                   QString msgjson="{"+msglist0[i];
                   qDebug()<<"===3===解析json文件错误 针对性解包=======msgjson==================: "<<msgjson;

                   jsonlist.push_back(msgjson);
               }
           }
        }
        //把拆分出来的json数据再次解析
       if(jsonlist.size()>0){
           for (int i = 0; i <jsonlist.size() ; ++i) {
                // parseJson(jsonlist[i]);
                 //数据加入队列
                 instructionMessageQueue.push(jsonlist[i]);
           }
       }
        return;
    }


    QJsonObject jsonObject = document.object();
    QString type = jsonObject["type"].toString();
    // 请求机器人实时数据
    if(type=="callback"){// "/api/request_data"
       // qDebug()<<"jsonObject[topic]=="<<jsonObject["topic").toString();
       // api_robot_data(jsonObject);


      if(  jsonObject["command"].toString()=="/api/car_robot_status"){
                //todo sukai 2021-11-04 当状态较之前改变时会自动返回数据
                api_car_robot_status(jsonObject);

       }


        return;
    }
//    qDebug()<<"jsonObject[type]=="<<jsonObject["type").toString();
//    qDebug()<<"jsonObject[command]=="<<jsonObject["command").toString();
//    qDebug()<<"jsonObject[uuid]=="<<jsonObject["uuid").toString();
//    qDebug()<<"jsonObject[error_message]=="<<jsonObject["error_message").toString();
//    qDebug()<<"jsonObject[status]=="<<jsonObject["status").toString();

    //todo sukai 2021-11-04 获取marker点位列表,名字testInfo
    if(  jsonObject["command"].toString()=="/api/markers/query_name_list"){
        //todo sukai 2021-11-04 获取marker点位列表,名字
        api_markers_query_name_list(jsonObject);
    }else if(  jsonObject["command"].toString()=="/api/get_params"){
        //todo sukai 2021-11-04 获取设置的参数
        api_get_params(jsonObject);
    }else if(  jsonObject["command"].toString()=="/api/robot_status_read"){
        //todo sukai 2021-11-04 小车当前的运行状态 调一次返回一次
        api_robot_status_read(jsonObject);
    }else if(  jsonObject["command"].toString()=="/api/car_robot_status"){
        //todo sukai 2021-11-04 小车当前的运行状态 自动返回
        api_car_robot_status(jsonObject);
    }else if(  jsonObject["command"].toString()=="/api/robot_arriveStatus"){
        //todo sukai 2021-11-04  每到达一个点位就会返回对应的数据
        api_robot_arriveStatus(jsonObject);
      }else if(  jsonObject["command"].toString()=="/api/getMapNamelist"){
        //todo sukai 2021-11-05 获所有地图名称
         api_getMapNamelist(jsonObject);
      }else if(  jsonObject["command"].toString()=="/api/robot_info"){
        //todo sukai 2021-11-05  获取机器人信息
         api_robot_info(jsonObject);
      }else if(  jsonObject["command"].toString()=="/api/taskpose/query_list"){
        //todo sukai 2021-11-07 获取任务表数据
         api_taskpose_query_list(jsonObject);
      }else if(  jsonObject["command"].toString()=="/api/time/query"){
        //todo sukai 2021-11-07 定时任务
         api_time_query(jsonObject);
      }else if(  jsonObject["command"].toString()=="/api/costmapLayer/query"){
        //todo sukai 2022-01-17 虚拟墙
         api_costmapLayer_query(jsonObject);
      }else if(  jsonObject["command"].toString()=="/api/saveGmappingMap"){//保存地图反馈
        //todo sukai 2021-11-25 保存地图反馈
        api_saveGmappingMap(jsonObject);
      }else if(  jsonObject["command"].toString()=="/api/getNodeNameList"){
        //todo sukai 2021-11-30 获取所有运行的 node节点的名称
        api_nodeName_List(jsonObject);
      }else if(  jsonObject["command"].toString()=="/api/registerServiceResult"){
        //todo sukai 2022-01-22
        api_registerServiceResult(jsonObject);
      }else if(  jsonObject["command"].toString()=="/api/qqqqq"){
        //todo sukai=============================
       // api_robot_status1111(jsonObject);
      }else if(  jsonObject["command"].toString()=="/api/qqqqq"){
        //todo sukai==========================
       // api_robot_status111(jsonObject);
      }else if(  jsonObject["command"].toString()=="/api/qqqqq"){
          // 获得机器人当前的全局状态
       //  api_robot_status111(jsonObject);
       }else if(  jsonObject["command"].toString()=="/api/request_data"){

      /**
      * 请求机器人实时数据
      * 请求server端以一定频率发送topic类型的数据。当请求成功后，server端会以一定频率发送数据给请求的client。
      * /api/request_data?topic=robot_status&frequency=1
      * // 请求server以1HZ的频率发送机器人全局状态
      */

      api_robot_data(jsonObject);
  }else if(  jsonObject["command"].toString()=="/api/markers/insert") {//点位（marker）功能接口;在机器人的当前位置和楼层标记锚点(marker)。

  }else if(  jsonObject["command"].toString()=="/api/markers/count") {//获取当前地图中的点位数量。
     //获取当前地图中的点位数量。
     api_markers_count(jsonObject);
  }else if(  jsonObject["command"].toString()=="/api/markers/query_brief") {
      // 获取点位摘要信息
    api_markers_query_brief(jsonObject);

  }else if(  jsonObject["command"].toString()=="/api/markers/insert_by_pose") {
      /**
       * 在指定位置添加marker.
       * /api/markers/insert_by_pose?name=205_room&x=-0.1&y=1.0&theta=0.0&floor=2&type=0
         //调用该接口，在位置(0.1,1.0), 方向(0.0), 楼层为2的位置添加名字为205_room的marker, 类型为一般点位。
       */
      api_markers_insert_by_pose(jsonObject);
  }else if(  jsonObject["command"].toString()=="/api/request_dataqq") {

  }else if(  jsonObject["command"].toString()=="/api/request_dataqq") {

  }else if(  jsonObject["command"].toString()=="/api/request_dataqq") {

  }






}
//todo sukai 2021-11-04 获取marker点位列表,名字testInfo
void  IIMTDriver::api_markers_query_name_list(QJsonObject &jsonObject){

    if(jsonObject["status"].toString()=="OK" ){
        QString number = jsonObject["number"].toString();
        if(jsonObject.contains(QString::fromStdString("results")))
        {
            QJsonValue jsonValueList = jsonObject.value(QString::fromStdString("results"));
            QJsonObject item = jsonValueList.toObject();
            if(item.contains(QString::fromStdString("meeting_room"))){
                QJsonValue jsonValueList1 = item.value(QString::fromStdString("meeting_room"));
                const QJsonArray &array = jsonValueList1.toArray();
                testInfos.clear();//清除原有数据
                maptestInfos_list.clear();
                for (int i = 0; i <array.size() ; ++i) {
//                    qDebug()<<"array.at(i);=="<< array.at(i);//// 点位名称：点位类型-楼层
//                    qDebug()<<"markId=="<<array.at(i).toObject().value("markId").toInt();// 点位名称：点位类型-楼层
//                    qDebug()<<"marker_name=="<<array.at(i).toObject().value("marker_name").toString();//// 点位名称：点位类型-楼层
//                    qDebug()<<"marker_name=="<<array.at(i).toObject().value("aaaa").toString();//// 点位名称：点位类型-楼层
                                     TestInfo testInfo_marker;
                                   //  std::map<QString, QString> *testInfoMap =new std::map<QString, QString> ();
                                     QMap<QString, QString> testInfo_Map;
                                     //==========================map封装==========================================

                                     testInfo_Map["markId"] = QString::number(array.at(i).toObject().value("markId").toInt());
                                     testInfo_Map["name"]=array.at(i).toObject().value("marker_name").toString();//标点名称
                                     testInfo_Map["mapName"]=array.at(i).toObject().value("mapName").toString();//地图名字
                                     testInfo_Map["floor"]=array.at(i).toObject().value("floor").toString();//点位所在的当前楼层
                                     testInfo_Map["type"]=array.at(i).toObject().value("typeId").toString(); //点位类型
                                     testInfo_Map["num"]=array.at(i).toObject().value("markNum").toString();  //点位编码
                                     testInfo_Map["x"]=array.at(i).toObject().value("x").toString();// 点位x坐标
                                     testInfo_Map["y"]=array.at(i).toObject().value("y").toString(); //点位y坐标
                                     testInfo_Map["qz"]=array.at(i).toObject().value("qz").toString();  //点位QZ 四元素
                                     testInfo_Map["qw"]=array.at(i).toObject().value("qw").toString();  //点位QW 四元素
                                     testInfo_Map["theta"]=array.at(i).toObject().value("yaw").toString(); //点位欧拉角 z
                                     testInfo_Map["merchantNumber"]=array.at(i).toObject().value("merchantNumber").toString();  //商户编号
                                     testInfo_Map["merchantName"]=array.at(i).toObject().value("merchantName").toString(); //商户名称
                                     testInfo_Map["status"]=array.at(i).toObject().value("status").toString(); //当前目点位状态
                                     testInfo_Map["command"]=array.at(i).toObject().value("command").toString(); //到目的地后需要 tcp 发送这条消息出去操作其它设备，比如机械臂
                                     testInfo_Map["commandStatus"]=array.at(i).toObject().value("commandStatus").toString(); //是否启用 Command 发送tcp命令，-1：不发送Command； 1：发送Command；



                                     //testInfo_Map["markId"] = QString::number(array.at(i)["markId"].toInt());
                                     //testInfo_Map["name"]=array.at(i)["marker_name"].toString();//标点名称
                                     //testInfo_Map["mapName"]=array.at(i)["mapName"].toString();//地图名字
                                     //testInfo_Map["floor"]=array.at(i)["floor"].toString();//点位所在的当前楼层
                                     //testInfo_Map["type"]=array.at(i)["typeId"].toString(); //点位类型
                                     //testInfo_Map["num"]=array.at(i)["markNum"].toString();  //点位编码
                                     //testInfo_Map["x"]=array.at(i)["x"].toString();// 点位x坐标
                                     //testInfo_Map["y"]=array.at(i)["y"].toString(); //点位y坐标
                                     //testInfo_Map["qz"]=array.at(i)["qz"].toString();  //点位QZ 四元素
                                     //testInfo_Map["qw"]=array.at(i)["qw"].toString();  //点位QW 四元素
                                     //testInfo_Map["theta"]=array.at(i)["yaw"].toString(); //点位欧拉角 z
                                     //testInfo_Map["merchantNumber"]=array.at(i)["merchantNumber"].toString();  //商户编号
                                     //testInfo_Map["merchantName"]=array.at(i)["merchantName"].toString(); //商户名称
                                     //testInfo_Map["status"]=array.at(i)["status"].toString(); //当前目点位状态
                                     //testInfo_Map["command"]=array.at(i)["command"].toString(); //到目的地后需要 tcp 发送这条消息出去操作其它设备，比如机械臂
                                     //testInfo_Map["commandStatus"]=array.at(i)["commandStatus"].toString(); //是否启用 Command 发送tcp命令，-1：不发送Command； 1：发送Command；

                                     maptestInfos_list.push_back(testInfo_Map);
                                     //==========================testInfo==========================================
                                             testInfo_marker.Id=array.at(i).toObject().value("markId").toInt();//mark标点id号
                                     testInfo_marker.TargetName=array.at(i).toObject().value("marker_name").toString();//标点名称
                                     testInfo_marker.Robotfloor=array.at(i).toObject().value("floor").toString();//点位所在的当前楼层
                                 testInfo_marker.MerchantNumber=array.at(i).toObject().value("merchantNumber").toString();  //商户编号
                                   testInfo_marker.MerchantName=array.at(i).toObject().value("merchantName").toString(); //商户名称
                                        testInfo_marker.MapName=array.at(i).toObject().value("mapName").toString();//地图名字
                                         testInfo_marker.TypeId=array.at(i).toObject().value("typeId").toString(); //标点类型
                                        testInfo_marker.MarkNum=array.at(i).toObject().value("markNum").toString();  //点位编码
                                              testInfo_marker.X=array.at(i).toObject().value("x").toString();// 点位x坐标
                                              testInfo_marker.Y=array.at(i).toObject().value("y").toString(); //点位y坐标
                                             testInfo_marker.QZ=array.at(i).toObject().value("qz").toString();  //点位QZ 四元素
                                             testInfo_marker.QW=array.at(i).toObject().value("qw").toString();  //点位QW 四元素
                                            testInfo_marker.YAW=array.at(i).toObject().value("yaw").toString(); //点位欧拉角 z
                                         testInfo_marker.Status=array.at(i).toObject().value("status").toString(); //当前目标点状态
                                        testInfo_marker.Command=array.at(i).toObject().value("command").toString(); //到目的地后需要 tcp 发送这条消息出去操作其它设备，比如机械臂
                                  testInfo_marker.CommandStatus=array.at(i).toObject().value("commandStatus").toString(); //是否启用 Command 发送tcp命令，-1：不发送Command； 1：发送Command；

                                     testInfos.push_back(testInfo_marker);

                }

                //sukai 路点数据，通过函数传到ui去
                if(maptestInfos_list_CallBack!=nullptr){
                    maptestInfos_list_CallBack(testInfos);
                }



                 if(kSDemoDlg_testInfo_flg==1){
                     //sukai 路点数据 传到编辑类 KSDemoDlg 中  | QList<KeyValue> maptestInfos_list;
                     if(kSDemoDlg_testInfos_list_CallBack!=nullptr){
                         kSDemoDlg_testInfos_list_CallBack(maptestInfos_list);
                     }

                      kSDemoDlg_testInfo_flg=-1;
                 }

//                 int kSDemoDlg_testInfo_flg=1;
//                 int kSDemoDlg_dictionarie_flg=1;
//                 int kSDemoDlg_task_pose_list_flg=1;
//                 int kSDemoDlg_task_time_list_flg=1;

            }
           //  QList<KeyValue> maptestInfos_list;
           // for(int i=0; i<maptestInfos_list.size(); i++)
          //  {

//                std::map<QString, QString> _map1;
//               // std::map<QString, QString> keyValue_map;
//                std::map<QString, QString>::iterator iter3;
//                //iter = maptestInfos_list.at(i).keyValue_map.begin();
//               iter3 = _map1.begin();
//                while(iter3 !=  maptestInfos_list.at(i).keyValue_map.end()) {
//                   // cout << iter3->first << " : " << iter3->second << endl;
//                    iter3++;
//                }

//                map<int, int> _map;
//                   _map[0] = 1;
//                   _map[1] = 2;
//                   _map[10] = 10;

//                   map<int, int>::iterator iter1;
//                   iter1 = _map.begin();
//                   while(iter1 != _map.end()) {
//                       cout << iter1->first << " : " << iter1->second << endl;
//                       iter1++;
//                   }

               //遍历
//                QMap<QString, QString>::reverse_iterator   iter;
//                for(iter = maptestInfos_list.at(i).rbegin(); iter != maptestInfos_list.at(i).rend(); iter++){
//                     qDebug()<<"==============maptestInfos_list===================";
//                     qDebug()<<"maptestInfos_list map-> mapName: "<<iter->first<<"map-> robotfloor: "<<iter->second;
//                     qDebug()<<"===============maptestInfos_list==================";
//               }


//                QMap<QString, QString>::const_iterator iter = maptestInfos_list.at(i).begin();
//                     while (iter != maptestInfos_list.at(i).end())
//                     {
//                         qDebug() << "==================Iterator================== " << iter.key() << ":" << iter.value(); // 迭代器

//                         iter++;

//                     }

        //    }

//            for (int i = 0; i <testInfos.size() ; ++i) {
//                qDebug()<<" Id =="<<testInfos.at(i).Id;//// id
//                qDebug()<<" TargetName =="<<testInfos.at(i).TargetName;//  点位名称：点位类型-楼层
//                qDebug()<<" Robotfloor =="<<testInfos.at(i).Robotfloor;//// 点位名称：点位类型-楼层
//                qDebug()<<" MerchantNumber =="<<testInfos.at(i).MerchantNumber;//// 点位名称：点位类型-楼层
//                qDebug()<<" MerchantName =="<<testInfos.at(i).MerchantName;//// 点位名称：点位类型-楼层
//                qDebug()<<" MapName =="<<testInfos.at(i).MapName;//// 点位名称：点位类型-楼层
//                qDebug()<<" TypeId =="<<testInfos.at(i).TypeId;//// 点位名称：点位类型-楼层
//                qDebug()<<" MarkNum =="<<testInfos.at(i).MarkNum;//// 点位名称：点位类型-楼层
//                qDebug()<<" X =="<<testInfos.at(i).X;//// 点位名称：点位类型-楼层
//                qDebug()<<" Y =="<<testInfos.at(i).Y;//// 点位名称：点位类型-楼层
//                qDebug()<<" QZ =="<<testInfos.at(i).QZ;//// 点位名称：点位类型-楼层
//                qDebug()<<" QW =="<<testInfos.at(i).QW;//// 点位名称：点位类型-楼层
//                qDebug()<<" YAW =="<<testInfos.at(i).YAW;//// 点位名称：点位类型-楼层
//                qDebug()<<" Status =="<<testInfos.at(i).Status;//// 点位名称：点位类型-楼层

//            }

        }
    }else{
        qDebug()<<"error api_markers_insert_by_pose   error"<< "添加失败！";//// 点位名称：点位类型-楼层

    }
}

//todo sukai 2021-11-04 获取设置的参数
void  IIMTDriver::api_get_params(QJsonObject &jsonObject){

    if(jsonObject["status"].toString()=="OK" ){
        QString number = jsonObject["number"].toString();
        if(jsonObject.contains(QString::fromStdString("results")))
        {
            QJsonValue jsonValueList = jsonObject.value(QString::fromStdString("results"));
            QJsonObject item = jsonValueList.toObject();
            if(item.contains(QString::fromStdString("params"))){
                QJsonValue jsonValueList1 = item.value(QString::fromStdString("params"));
                const QJsonArray &array = jsonValueList1.toArray();
                dictionaries_s.clear();//list 清除原有数据
                dictionariesMap.clear();//map 清除原有数据
                mapdictionarie_list.clear();
                dictionariesMap_ui.clear();
                for (int i = 0; i <array.size() ; ++i) {
                                     QMap<QString, QString> dictionaries_Map;
                                     //==========================map封装==========================================
                                     dictionaries_Map["id"] = QString::number(array.at(i).toObject().value("id").toInt());
                                     dictionaries_Map["targetName"]=array.at(i).toObject().value("targetName").toString();//名称
                                     dictionaries_Map["key"]=array.at(i).toObject().value("key").toString();//key
                                     dictionaries_Map["value"]=array.at(i).toObject().value("value").toString();//值
                                     dictionaries_Map["status"]=array.at(i).toObject().value("status").toString(); //默认 0 状态  0：正常  -1：暂停使用

                                     mapdictionarie_list.push_back(dictionaries_Map);
                                     //==========================dictionaries==========================================
                                     Dictionaries dictionaries;
                                     dictionaries.Id=array.at(i).toObject().value("id").toInt();//字典id号
                                     dictionaries.TargetName=array.at(i).toObject().value("targetName").toString();//名称
                                     dictionaries.Key=array.at(i).toObject().value("key").toString();//key
                                     dictionaries.Value=array.at(i).toObject().value("value").toString(); //值
                                     dictionaries.Status=array.at(i).toObject().value("status").toString(); //默认 0 状态  0：正常  -1：暂停使用
                                     //封装成 list
                                     dictionaries_s.push_back(dictionaries);
                                     //封装成 map
                                     dictionariesMap_ui[array.at(i).toObject().value("key").toString()] = array.at(i).toObject().value("value").toString();


                }
                //sukai 字典数据 通过函数传到ui去

                if(mapdictionarie_list_CallBack!=nullptr){
                   mapdictionarie_list_CallBack(dictionaries_s);
                }


                if(kSDemoDlg_dictionarie_flg==1){
                    //sukai 字典数据 传到编辑类 KSDemoDlgtaskparamer 中
                    if(kSDemoDlg_dictionarie_list_CallBack!=nullptr){
                       kSDemoDlg_dictionarie_list_CallBack(mapdictionarie_list);
                    }



                     kSDemoDlg_dictionarie_flg=-1;
                }




            }

//            for (int i = 0; i <dictionaries_s.size() ; ++i) {
//                qDebug()<<" Id =="<<dictionaries_s.at(i).Id;//// id
//                qDebug()<<" TargetName =="<<dictionaries_s.at(i).TargetName;//
//                qDebug()<<" Key =="<<dictionaries_s.at(i).Key;////
//                qDebug()<<" Value =="<<dictionaries_s.at(i).Value;//
//                qDebug()<<" Status =="<<dictionaries_s.at(i).Status;//
//            }

        }
    }else{
        qDebug()<<"获取设置的参数 get_params"<< "添加失败！";//// 点位名称：点位类型-楼层

    }
}

// todo sukai 2021-11-04  小车当前的运行状态 调一次返回一次
void  IIMTDriver::api_robot_status_read(QJsonObject &jsonObject){
    if(jsonObject["status"].toString()=="OK" ){
       robot_status = jsonObject["result"].toString();
       //sukai 小车的运行状态 通过函数传到ui去


       if(robot_status_CallBack!=nullptr){
         robot_status_CallBack(robot_status);
       }





       qDebug()<<"robot_status： "<<robot_status;//
/**
       小车当前的运行状态

                类型	说明
                ActionStatusWaitingForStart	动作正在等待开始。
                ActionStatusRunning	动作正在进行。
                ActionStatusFinished	动作已经完成。
                ActionStatusPaused	动作已经暂停。
                ActionStatusStopped	动作已经停止（取消）。
                ActionStatusError	动作执行过程中出现错误。
                LOST  刚启动程序，就是输出LOST；
*/
    }
}

// todo sukai 2021-11-04  当状态较之前改变时会自动返回数据
void  IIMTDriver::api_car_robot_status(QJsonObject &jsonObject){
    if(jsonObject["status"].toString()=="OK" ){
       robot_status = jsonObject["result"].toString();
       //sukai 小车的运行状态 通过函数传到ui去 == 实时，改变后实时传送

       if(robot_status_CallBack!=nullptr){
         robot_status_CallBack(robot_status);
       }




       qDebug()<<"robot_status： "<<robot_status;//
/**
       小车当前的运行状态

                类型	说明
                ActionStatusWaitingForStart	动作正在等待开始。
                ActionStatusRunning	动作正在进行。
                ActionStatusFinished	动作已经完成。
                ActionStatusPaused	动作已经暂停。
                ActionStatusStopped	动作已经停止（取消）。
                ActionStatusError	动作执行过程中出现错误。
                LOST  刚启动程序，就是输出LOST；
*/
    }
}

//todo sukai 2021-11-04  每到达一个点位就会返回对应的数据
void  IIMTDriver::api_robot_arriveStatus(QJsonObject &jsonObject){

       arriveRobot.arriveType = jsonObject["arriveType"].toString();//是否是备用路点 ,string类型-> ture:是备用路点 ;string类型-> fase:不是备用路点
       arriveRobot.arriveObjectName = jsonObject["arriveObjectName"].toString();// tcp客户端名字->发送的命令
       arriveRobot.arriveTaskName = jsonObject["arriveTaskName"].toString();// 取第几个托盘,发送/api/markers/insert未传递对应的task将返回 EMPTY
       arriveRobot.arrivetargetName = jsonObject["arrivetargetName"].toString();// 到达的房间
       arriveRobot.arriveCommand = jsonObject["arriveCommand"].toString();//到目的地后需要 tcp 发送这条消息出去操作其它设备，比如机械臂
       arriveRobot.arriveCommandStatus = jsonObject["arriveCommandStatus"].toString();//是否启用 Command 发送tcp命令，-1：不发送Command； 1：发送Command；
       arriveRobot.arriveMessage = jsonObject["arriveMessage"].toString();//message： 接收客户端发来的消息，目标到达后完整返回给客户端
       arriveRobot.arriveStatus = jsonObject["arriveStatus"].toString();//success: 成功 ； aborted：未到达目的地；  preempted：用户取消操作

       qDebug()<<"arriveRobot.arrivetargetName "<<arriveRobot.arrivetargetName;

       //sukai 到达点位后返回的数据 通过函数传到ui去

       if(arriveRobot_CallBack!=nullptr){
         arriveRobot_CallBack(arriveRobot);
       }





}

//todo sukai 2021-11-04 获所有地图名称  {"mapName":"indoor","robotfloor":"1,2,3,4..."}
void  IIMTDriver::api_getMapNamelist(QJsonObject &jsonObject){

    if(jsonObject["status"].toString()=="OK" ){
       QString number = jsonObject["number"].toString();
        if(jsonObject.contains(QString::fromStdString("results")))
        {
            QJsonValue jsonValueList = jsonObject.value(QString::fromStdString("results"));
            QJsonObject item = jsonValueList.toObject();
            if(item.contains(QString::fromStdString("map"))){
                QJsonValue jsonValueList1 = item.value(QString::fromStdString("map"));
                const QJsonArray &array = jsonValueList1.toArray();
                mapNames.clear();//清除原有数据
                mapNames_list.clear();
                for (int i = 0; i <array.size() ; ++i) {
                 //   qDebug()<<"mapName=="<<array.at(i).toObject().value("mapName").toString();//// 地图名称
                 //   qDebug()<<"robotfloor=="<<array.at(i).toObject().value("robotfloor").toString();//// 楼层
                                    MapName mapName;
                                    QMap<QString,std::vector<std::string>> MapName_Map;
                                     //获取地图名称
                                    // QList<MapName> mapNames;
                                     mapName.mapName=array.at(i).toObject().value("mapName").toString();//地图名称
                                     QString robotfloors = array.at(i).toObject().value("robotfloor").toString();//地图楼层
                                     try {
                                             //分割文件名称 1,2,3,4,,5
                                             //字符串分割函数
                                              mapName.robotfloors =  split(",",robotfloors.toStdString());
                                              MapName_Map[array.at(i).toObject().value("mapName").toString()]=mapName.robotfloors;
                                      mapNames_list.push_back(MapName_Map);
                                      mapNames.push_back(mapName);
                                     }catch (std::exception e){

                                         std::cout<<"getOnlyFileName"<<std::endl;
                                     }

                }

                //sukai 获取地图名称 通过函数传到ui去



                if(mapNames_list_CallBack!=nullptr){
                   mapNames_list_CallBack(mapNames_list);
                }



            }

            for (int i = 0; i <mapNames.size() ; ++i) {
            //    qDebug()<<"地图名称 mapName =="<<mapNames.at(i).mapName;//// id
                  std::vector<std::string> robotfloorslist = mapNames.at(i).robotfloors;
                 for (int y = 0; y <robotfloorslist.size() ; ++y) {
                      // qDebug()<<"楼层 robotfloor =="<<QString::fromStdString(robotfloorslist.at(y));//楼层
                 }

            }

        }
    }
}

//todo sukai 2021-11-04 调用接口可以获取机器人的一些基本信息。
void  IIMTDriver::api_robot_info(QJsonObject &jsonObject){

    if(jsonObject["status"].toString()=="OK" ){
        QString number = jsonObject["number"].toString();
        if(jsonObject.contains(QString::fromStdString("results")))
        {
            QJsonValue jsonValueList = jsonObject.value(QString::fromStdString("results"));
            QJsonObject item = jsonValueList.toObject();
            if(item.contains(QString::fromStdString("robot_info"))){
                QJsonValue jsonValueList1 = item.value(QString::fromStdString("robot_info"));
                const QJsonArray &array = jsonValueList1.toArray();

                                    if (array.size()<=0)
                                         return;

                                     robot_info.robotNumber=array.at(0).toObject().value("robotNumber").toInt();//机器人编号
                                     robot_info.merchantNumber=array.at(0).toObject().value("merchantNumber").toString();//商户编号
                                     robot_info.merchantName=array.at(0).toObject().value("merchantName").toString();//商户名称
                                     robot_info.velspeed=array.at(0).toObject().value("velspeed").toString(); //机器人线速度
                                     robot_info.angularSpeed=array.at(0).toObject().value("angularSpeed").toString(); //机器人角速度
                                     robot_info.ip_address=array.at(0).toObject().value("ip_address").toString(); //机器人热点地址
                                     robot_info.ip_address_prot=array.at(0).toObject().value("ip_address_prot").toString(); //机器人端口
                                     robot_info.waitGoalTime=array.at(0).toObject().value("waitGoalTime").toString(); //每个目标点停留的时间 当：waitIsNotGo：-1 时 ； waitGoalTime 无效
                                     robot_info.waitIsNotGo=array.at(0).toObject().value("waitIsNotGo").toString(); // waitIsNotGo = 1：到达目标点后自动运行下一个点， -1：不自动运行下一个点 ； | waitIsNotGo：-1 时 waitGoalTime 无效
                                     robot_info.enableFlag=array.at(0).toObject().value("enableFlag").toString(); //// 软急停 电机使能true 电机失能false


            }


                qDebug()<<" robotNumber =="<<robot_info.robotNumber;//// id
                qDebug()<<" merchantNumber =="<<robot_info.merchantNumber;//
                qDebug()<<" merchantName =="<<robot_info.merchantName;////
                qDebug()<<" velspeed =="<<robot_info.velspeed;//
                qDebug()<<" angularSpeed =="<<robot_info.angularSpeed;//
                qDebug()<<" ip_address =="<<robot_info.ip_address;//// id
                qDebug()<<" ip_address_prot =="<<robot_info.ip_address_prot;//
                qDebug()<<" waitGoalTime =="<<robot_info.waitGoalTime;////
                qDebug()<<" waitIsNotGo =="<<robot_info.waitIsNotGo;//
                qDebug()<<" enableFlag =="<<robot_info.enableFlag;//

                //sukai 机器人的一些基本信息 通过函数传到ui去

                if(robot_info_CallBack!=nullptr){
                 robot_info_CallBack( robot_info);
                }



        }
    }else{
        qDebug()<<"error api_markers_insert_by_pose   error"<< "添加失败！";//// 点位名称：点位类型-楼层

    }
}

//todo sukai 2021-11-07 获取任务表数据
void  IIMTDriver::api_taskpose_query_list(QJsonObject &jsonObject){

    if(jsonObject["status"].toString()=="OK" ){
        QString number = jsonObject["number"].toString();
        if(jsonObject.contains(QString::fromStdString("results")))
        {
            QJsonValue jsonValueList = jsonObject.value(QString::fromStdString("results"));
            QJsonObject item = jsonValueList.toObject();
            if(item.contains(QString::fromStdString("taskpose"))){
                QJsonValue jsonValueList1 = item.value(QString::fromStdString("taskpose"));
                const QJsonArray &array = jsonValueList1.toArray();
                taskPOSEs.clear();//清除原有数据
                maptaskPOSEMaps_list.clear();
                for (int i = 0; i <array.size() ; ++i) {
                    qDebug()<<"array.at(i);=="<< array.at(i);//// 点位名称：点位类型-楼层
                    qDebug()<<"markId=="<<array.at(i).toObject().value("id").toInt();// 点位名称：点位类型-楼层
                    qDebug()<<"marker_name=="<<array.at(i).toObject().value("marker_name").toString();//// 点位名称：点位类型-楼层
                    qDebug()<<"marker_name=="<<array.at(i).toObject().value("aaaa").toString();//// 点位名称：点位类型-楼层
                                     TaskPOSE taskPOSE_marker;
                                     QMap<QString, QString> taskPOSEMap;
                                     //==========================map封装==========================================
                                     taskPOSEMap["id"] = QString::number(array.at(i).toObject().value("id").toInt());
                                     taskPOSEMap["marker_name"]=array.at(i).toObject().value("marker_name").toString();//标点名称
                                     taskPOSEMap["taskName"]=array.at(i).toObject().value("taskName").toString();////谁发的任务,第几个餐盘下发的任务
                                     taskPOSEMap["robotNumber"]=array.at(i).toObject().value("robotNumber").toString();//机器人编号
                                     taskPOSEMap["orderNum"]=QString::number(array.at(i).toObject().value("orderNum").toInt());//执行顺序
                                     taskPOSEMap["mapName"]=array.at(i).toObject().value("mapName").toString();//地图名字
                                     taskPOSEMap["floor"]=array.at(i).toObject().value("floor").toString();//点位所在的当前楼层
                                     taskPOSEMap["typeId"]=array.at(i).toObject().value("typeId").toString(); //点位类型
                                     taskPOSEMap["markNum"]=array.at(i).toObject().value("markNum").toString();  //点位编码
                                     taskPOSEMap["x"]=array.at(i).toObject().value("x").toString();// 点位x坐标
                                     taskPOSEMap["y"]=array.at(i).toObject().value("y").toString(); //点位y坐标
                                     taskPOSEMap["qz"]=array.at(i).toObject().value("qz").toString();  //点位QZ 四元素
                                     taskPOSEMap["qw"]=array.at(i).toObject().value("qw").toString();  //点位QW 四元素
                                     taskPOSEMap["theta"]=array.at(i).toObject().value("yaw").toString(); //点位欧拉角 z
                                     taskPOSEMap["merchantNumber"]=array.at(i).toObject().value("merchantNumber").toString();  //商户编号
                                     taskPOSEMap["merchantName"]=array.at(i).toObject().value("merchantName").toString(); //商户名称
                                     taskPOSEMap["controller"]=array.at(i).toObject().value("controller").toString(); //控制其它操作,比如电梯，设备2消毒
                                     taskPOSEMap["status"]=array.at(i).toObject().value("status").toString(); //当前目点位状态
                                     taskPOSEMap["taskStatus"]=array.at(i).toObject().value("taskStatus").toString(); //当前任务状态 0：未开始  1：机器人正在前往该目标点 ; 2:机器人已经到达该点的目标备用点

                                     taskPOSEMap["command"]=array.at(i).toObject().value("command").toString(); //到目的地后需要 tcp 发送这条消息出去操作其它设备，比如机械臂
                                     taskPOSEMap["commandStatus"]=array.at(i).toObject().value("commandStatus").toString(); //是否启用 Command 发送tcp命令，-1：不发送Command； 1：发送Command；
                                     taskPOSEMap["message"]=array.at(i).toObject().value("message").toString(); //message： 接收客户端发来的消息，目标到达后完整返回给客户端

                                     taskPOSEMap["socketObjectName"]=array.at(i).toObject().value("socketObjectName").toString(); //记录是哪个客户端发送的命令
                                     taskPOSEMap["time"]=array.at(i).toObject().value("time").toString(); //插入时间

                                     maptaskPOSEMaps_list.push_back(taskPOSEMap);
                                     //==========================testInfo==========================================
                                    taskPOSE_marker.Id=array.at(i).toObject().value("id").toInt();//mark标点id号
                                    taskPOSE_marker.TargetName=array.at(i).toObject().value("marker_name").toString();//标点名称
                                    taskPOSE_marker.TaskName=array.at(i).toObject().value("taskName").toString();//谁发的任务,第几个餐盘下发的任务
                                    taskPOSE_marker.RobotNumber=array.at(i).toObject().value("robotNumber").toString();//机器人编号
                                    taskPOSE_marker.Order=QString::number(array.at(i).toObject().value("orderNum").toInt());//执行顺序;//执行顺序
                                    taskPOSE_marker.MerchantNumber=array.at(i).toObject().value("merchantNumber").toString();  //商户编号
                                    taskPOSE_marker.MerchantName=array.at(i).toObject().value("merchantName").toString(); //商户名称
                                    taskPOSE_marker.MapName=array.at(i).toObject().value("mapName").toString();//地图名字
                                    taskPOSE_marker.Robotfloor=array.at(i).toObject().value("floor").toInt();//点位所在的当前楼层
                                    taskPOSE_marker.TypeId=array.at(i).toObject().value("typeId").toString(); //标点类型
                                    taskPOSE_marker.MarkNum=array.at(i).toObject().value("markNum").toString();  //点位编码
                                    taskPOSE_marker.X=array.at(i).toObject().value("x").toString();// 点位x坐标
                                    taskPOSE_marker.Y=array.at(i).toObject().value("y").toString(); //点位y坐标
                                    taskPOSE_marker.QZ=array.at(i).toObject().value("qz").toString();  //点位QZ 四元素
                                    taskPOSE_marker.QW=array.at(i).toObject().value("qw").toString();  //点位QW 四元素
                                    taskPOSE_marker.YAW=array.at(i).toObject().value("yaw").toString(); //点位欧拉角 z
                                    taskPOSE_marker.Status=array.at(i).toObject().value("status").toString(); //当前目标点状态
                                    taskPOSE_marker.TaskStatus=array.at(i).toObject().value("taskStatus").toString(); //当前任务状态 0：未开始  1：机器人正在前往该目标点 ; 2:机器人已经到达该点的目标备用点
                                    taskPOSE_marker.Controller=array.at(i).toObject().value("controller").toString(); //控制其它操作,比如电梯，设备2消毒
                                    taskPOSE_marker.Command=array.at(i).toObject().value("command").toString(); //到目的地后需要 tcp 发送这条消息出去操作其它设备，比如机械臂
                                    taskPOSE_marker.CommandStatus=array.at(i).toObject().value("commandStatus").toString(); //是否启用 Command 发送tcp命令，-1：不发送Command； 1：发送Command；
                                     taskPOSE_marker.Message=array.at(i).toObject().value("message").toString();//message： 接收客户端发来的消息，目标到达后完整返回给客户端
                                     taskPOSE_marker.SocketObjectName=array.at(i).toObject().value("socketObjectName").toString();//记录是哪个客户端发送的命令
                                     taskPOSE_marker.Time=array.at(i).toObject().value("time").toString(); //插入时间
                                     taskPOSEs.push_back(taskPOSE_marker);


                }

                //sukai 执行路点任务 通过函数传到ui去

                if(maptaskPOSEMaps_list_CallBack!=nullptr){
                maptaskPOSEMaps_list_CallBack(taskPOSEs);
                }

                if(kSDemoDlg_task_pose_list_flg==1){
                    //sukai 执行路点任务 传到编辑类 KSDemoDlgtask 中
                    if(kSDemoDlg_task_pose_list_CallBack!=nullptr){
                    kSDemoDlg_task_pose_list_CallBack(maptaskPOSEMaps_list);
                    }


                     kSDemoDlg_task_pose_list_flg=-1;
                }




            }

//            for(int i=0; i<maptaskPOSEMaps_list.size(); i++)
//            {
//               //遍历

//                QMap<QString, QString>::const_iterator iter = maptestInfos_list.at(i).begin();
//                     while (iter != maptestInfos_list.at(i).end())
//                     {
//                         qDebug() << "==================maptaskPOSEMaps_list================== " << iter.key() << ":" << iter.value(); // 迭代器

//                         iter++;

//                     }

//            }

//            for (int i = 0; i <taskPOSEs.size() ; ++i) {
//                qDebug()<<" Id =="<<testInfos.at(i).Id;//// id
//                qDebug()<<" TargetName =="<<testInfos.at(i).TargetName;//  点位名称：点位类型-楼层
//                qDebug()<<" Robotfloor =="<<testInfos.at(i).Robotfloor;//// 点位名称：点位类型-楼层
//                qDebug()<<" MerchantNumber =="<<testInfos.at(i).MerchantNumber;//// 点位名称：点位类型-楼层
//                qDebug()<<" MerchantName =="<<testInfos.at(i).MerchantName;//// 点位名称：点位类型-楼层
//                qDebug()<<" MapName =="<<testInfos.at(i).MapName;//// 点位名称：点位类型-楼层
//                qDebug()<<" TypeId =="<<testInfos.at(i).TypeId;//// 点位名称：点位类型-楼层
//                qDebug()<<" MarkNum =="<<testInfos.at(i).MarkNum;//// 点位名称：点位类型-楼层
//                qDebug()<<" X =="<<testInfos.at(i).X;//// 点位名称：点位类型-楼层
//                qDebug()<<" Y =="<<testInfos.at(i).Y;//// 点位名称：点位类型-楼层
//                qDebug()<<" QZ =="<<testInfos.at(i).QZ;//// 点位名称：点位类型-楼层
//                qDebug()<<" QW =="<<testInfos.at(i).QW;//// 点位名称：点位类型-楼层
//                qDebug()<<" YAW =="<<testInfos.at(i).YAW;//// 点位名称：点位类型-楼层
//                qDebug()<<" Status =="<<testInfos.at(i).Status;//// 点位名称：点位类型-楼层

//            }

        }
    }else{
        qDebug()<<"error 获取任务表数据 ";//// 点位名称：点位类型-楼层

    }
}

//todo sukai 2021-11-07 定时任务
void  IIMTDriver::api_time_query(QJsonObject &jsonObject){

    if(jsonObject["status"].toString()=="OK" ){
        QString number = jsonObject["number"].toString();
        if(jsonObject.contains(QString::fromStdString("results")))
        {
            QJsonValue jsonValueList = jsonObject.value(QString::fromStdString("results"));
            QJsonObject item = jsonValueList.toObject();
            if(item.contains(QString::fromStdString("time_Task"))){
                QJsonValue jsonValueList1 = item.value(QString::fromStdString("time_Task"));
                const QJsonArray &array = jsonValueList1.toArray();
                Table_Tasks.clear();//list 清除原有数据
                mapTable_TaskMaps_list.clear();

                for (int i = 0; i <array.size() ; ++i) {
                                     QMap<QString, QString> Table_Task_Map;
                                     //==========================map封装==========================================
                                     Table_Task_Map["id"] = QString::number(array.at(i).toObject().value("id").toInt());
                                     Table_Task_Map["markName"]=array.at(i).toObject().value("markName").toString();//点位名字
                                     Table_Task_Map["robotNumber"]=array.at(i).toObject().value("robotNumber").toString();//机器人编号
                                     Table_Task_Map["equipment_1"]=array.at(i).toObject().value("equipment_1").toString();//设备1
                                     Table_Task_Map["equipment_2"]=array.at(i).toObject().value("equipment_2").toString();//设备2
                                     Table_Task_Map["startTime"]=array.at(i).toObject().value("startTime").toString();//开始时间 13:14【格式】精确到分
                                     Table_Task_Map["endTime"]=array.at(i).toObject().value("endTime").toString();//结束时间 15:19【格式】精确到分
                                     Table_Task_Map["status"]=array.at(i).toObject().value("status").toString(); //默认 0 状态  0：正常  -1：暂停使用
                                     Table_Task_Map["workingStatus"]=array.at(i).toObject().value("workingStatus").toString(); // running	动作正在进行 |finished 动作已经完成或等待开始

                                     mapTable_TaskMaps_list.push_back(Table_Task_Map);


                                     //==========================dictionaries==========================================
                                     Table_Task table_Task;
                                   QJsonObject json=  array.at(i).toObject();
                                   table_Task.Id=json.value("id").toInt();
                                   table_Task.TargetName=array.at(i).toObject().value("marker_name").toString();//点位名字
                                   table_Task.RobotNumber=array.at(i).toObject().value("robotNumber").toString();//机器人编号
                                   table_Task.Equipment_1=array.at(i).toObject().value("equipment_1").toString(); //设备1
                                   table_Task.Equipment_2=array.at(i).toObject().value("equipment_2").toString(); //设备2
                                   table_Task.StartTime=array.at(i).toObject().value("startTime").toString();//开始时间 13:14【格式】精确到分
                                   table_Task.EndTime=array.at(i).toObject().value("endTime").toString();//结束时间 15:19【格式】精确到分
                                   table_Task.Status=array.at(i).toObject().value("status").toString();//默认 0 状态  0：正常  -1：暂停使用
                                   table_Task.WorkingStatus=array.at(i).toObject().value("workingStatus").toString(); // running	动作正在进行 |finished 动作已经完成或等待开始

                                     //table_Task.Id=array.at(i).toObject().value("id").toInt();//id号
                                     //table_Task.TargetName=array.at(i).toObject().value("marker_name").toString();//点位名字
                                     //table_Task.RobotNumber=array.at(i).toObject().value("robotNumber").toString();//机器人编号
                                     //table_Task.Equipment_1=array.at(i).toObject().value("equipment_1").toString(); //设备1
                                     //table_Task.Equipment_2=array.at(i).toObject().value("equipment_2").toString(); //设备2
                                     //table_Task.StartTime=array.at(i).toObject().value("startTime").toString();//开始时间 13:14【格式】精确到分
                                     //table_Task.EndTime=array.at(i).toObject().value("endTime").toString();//结束时间 15:19【格式】精确到分
                                     //table_Task.Status=array.at(i).toObject().value("status").toString();//默认 0 状态  0：正常  -1：暂停使用
                                     //table_Task.WorkingStatus=array.at(i).toObject().value("workingStatus").toString(); // running	动作正在进行 |finished 动作已经完成或等待开始

                                   //封装成 list
                                     Table_Tasks.push_back(table_Task);



                }
                //sukai 定时任务 通过函数传到ui去

                if(mapTable_time_task_list_CallBack!=nullptr){
              mapTable_time_task_list_CallBack(Table_Tasks);
                }

                if(kSDemoDlg_task_time_list_flg==1){
                    //sukai 定时任务 传到编辑类 KSDemoDlgtaskTime 中

                     if(kSDemoDlg_task_time_list_CallBack!=nullptr){
                  kSDemoDlg_task_time_list_CallBack(mapTable_TaskMaps_list);
                     }

                     kSDemoDlg_task_time_list_flg=-1;
                }


            }

//            for (int i = 0; i <dictionaries_s.size() ; ++i) {
//                 qDebug()<<"==========Table_Task_Map==========================";//// id
//                qDebug()<<"============== Id =="<<dictionaries_s.at(i).Id;//// id
//                qDebug()<<" TargetName =="<<dictionaries_s.at(i).TargetName;//
//                qDebug()<<" Key =="<<dictionaries_s.at(i).Key;////
//                qDebug()<<" Value =="<<dictionaries_s.at(i).Value;//
//                qDebug()<<" Status =="<<dictionaries_s.at(i).Status;//
//            }

        }
    }else{
        qDebug()<<"获取设置的参数 get_params"<< "添加失败！";//// 点位名称：点位类型-楼层

    }
}

//todo sukai 2022-01-17 虚拟墙数据
void  IIMTDriver::api_costmapLayer_query(QJsonObject &jsonObject){

//    CostmapLayer costmapLayer;
//    QList<CostmapLayer> costmapLayers;
//    QList<QMap<QString, QString>> mapTable_CostmapLayer_list;

    if(jsonObject["status"].toString()=="OK" ){
        QString number = jsonObject["number"].toString();
        if(jsonObject.contains(QString::fromStdString("results")))
        {
            QJsonValue jsonValueList = jsonObject.value(QString::fromStdString("results"));
            QJsonObject item = jsonValueList.toObject();
            if(item.contains(QString::fromStdString("costmapLayer"))){
                QJsonValue jsonValueList1 = item.value(QString::fromStdString("costmapLayer"));
                const QJsonArray &array = jsonValueList1.toArray();
                costmapLayers.clear();//list 清除原有数据
                mapTable_CostmapLayer_list.clear();

                for (int i = 0; i <array.size() ; ++i) {


                                     QMap<QString, QString> CostmapLayer_Map;
                                     //==========================map封装==========================================
                                     CostmapLayer_Map["id"] = QString::number(array.at(i).toObject().value("id").toInt());
                                     CostmapLayer_Map["figureType"]=array.at(i).toObject().value("figureType").toString();//图形类型 point：点 至少1个点数据, line：线 至少2个点数据, polygons:多边形 至少3个点数据
                                     CostmapLayer_Map["figureName"]=array.at(i).toObject().value("figureName").toString();
                                     CostmapLayer_Map["merchantNumber"]=array.at(i).toObject().value("merchantNumber").toString();//商户编号 客户编号 比如龙源或者某个餐饮店比如海底捞1号店【每家店铺可能包含10台机器人，它们在同一个场景运行所以它们的客户编号都是一致的（方便多机协作）】
                                     CostmapLayer_Map["merchantName"]=array.at(i).toObject().value("merchantName").toString();//商户名称
                                     CostmapLayer_Map["mapName"]=array.at(i).toObject().value("mapName").toString();//地图名字
                                     CostmapLayer_Map["robotfloor"]=array.at(i).toObject().value("robotfloor").toString();//地图楼层
                                     CostmapLayer_Map["robotNumber"]=array.at(i).toObject().value("robotNumber").toString();//自研底盘机器人编号
                                     CostmapLayer_Map["point_A_X"]=array.at(i).toObject().value("point_A_X").toString(); // 第一个点位A
                                     CostmapLayer_Map["point_A_Y"]=array.at(i).toObject().value("point_A_Y").toString(); // 第一个点位A
                                     CostmapLayer_Map["point_B_X"]=array.at(i).toObject().value("point_B_X").toString(); // 第二个点位B
                                     CostmapLayer_Map["point_B_Y"]=array.at(i).toObject().value("point_B_Y").toString(); // 第二个点位B
                                     CostmapLayer_Map["point_C_X"]=array.at(i).toObject().value("point_C_X").toString(); // 第三个点位C
                                     CostmapLayer_Map["point_C_Y"]=array.at(i).toObject().value("point_C_Y").toString(); // 第三个点位C
                                     CostmapLayer_Map["point_D_X"]=array.at(i).toObject().value("point_D_X").toString(); // 第四个点位D
                                     CostmapLayer_Map["point_D_Y"]=array.at(i).toObject().value("point_D_Y").toString(); // 第四个点位D

                                     mapTable_CostmapLayer_list.push_back(CostmapLayer_Map);


                                     //==========================dictionaries==========================================
                                     CostmapLayer costmapLayer1;
                                   QJsonObject json=  array.at(i).toObject();
                                   costmapLayer1.Id=json.value("id").toInt();
                                   costmapLayer1.FigureType=array.at(i).toObject().value("figureType").toString();//
                                   costmapLayer1.FigureName=array.at(i).toObject().value("figureName").toString();//
                                   costmapLayer1.RobotNumber=array.at(i).toObject().value("merchantNumber").toString();//
                                   costmapLayer1.MerchantName=array.at(i).toObject().value("merchantName").toString(); //
                                   costmapLayer1.MapName=array.at(i).toObject().value("mapName").toString(); //
                                   costmapLayer1.POINT_A_X=array.at(i).toObject().value("point_A_X").toString();//
                                   costmapLayer1.POINT_A_Y=array.at(i).toObject().value("point_A_Y").toString();//
                                   costmapLayer1.POINT_B_X=array.at(i).toObject().value("point_B_X").toString();//
                                   costmapLayer1.POINT_B_Y=array.at(i).toObject().value("point_B_Y").toString();//
                                   costmapLayer1.POINT_C_X=array.at(i).toObject().value("point_C_X").toString();//
                                   costmapLayer1.POINT_C_Y=array.at(i).toObject().value("point_C_Y").toString();//
                                   costmapLayer1.POINT_D_X=array.at(i).toObject().value("point_D_X").toString();//
                                   costmapLayer1.POINT_D_Y=array.at(i).toObject().value("point_D_Y").toString();//


                                   //封装成 list
                                     costmapLayers.push_back(costmapLayer1);



                }


                    //sukai 虚拟墙 传到编辑类 KSDemoDlgtaskTime 中

                     if(kSDemoDlg_task_costmapLayer_list_CallBack!=nullptr){
                  kSDemoDlg_task_costmapLayer_list_CallBack(mapTable_CostmapLayer_list);
                     }
            }
        }
    }else{
        qDebug()<<"获取设置的参数 get_params"<< "添加失败！";//// 点位名称：点位类型-楼层

    }
}

//todo sukai 2021-11-25 保存地图反馈
void  IIMTDriver::api_saveGmappingMap(QJsonObject &jsonObject){
    if(jsonObject["status"].toString()=="OK" ){
       SaveGmappingMap saveGmappingMap;
       saveGmappingMap.status = jsonObject["status"].toString();
       saveGmappingMap.error_message = jsonObject["error_message"].toString();
       saveGmappingMap.mapName = robot_status = jsonObject["mapName"].toString();
       saveGmappingMap.robotfloor = robot_status = jsonObject["robotfloor"].toString();
       //sukai 保存地图反馈
       if(robot_saveGmappingMap_CallBack!=nullptr){
   robot_saveGmappingMap_CallBack(saveGmappingMap);
       }

       //qDebug()<<"saveGmappingMap "<<saveGmappingMap;//

    }else{
        SaveGmappingMap saveGmappingMap;
        saveGmappingMap.status = jsonObject["status"].toString();
        saveGmappingMap.error_message = jsonObject["error_message"].toString();
        saveGmappingMap.mapName = robot_status = jsonObject["mapName"].toString();
        saveGmappingMap.robotfloor = robot_status = jsonObject["robotfloor"].toString();
        //sukai 保存地图反馈

        if(robot_saveGmappingMap_CallBack!=nullptr){
        robot_saveGmappingMap_CallBack(saveGmappingMap);
        }

        //qDebug()<<"saveGmappingMap "<<saveGmappingMap;//
    }
}


//todo sukai 2021-11-30 获取所有运行的 node节点的名称
void  IIMTDriver::api_nodeName_List(QJsonObject &jsonObject){
    if(jsonObject["status"].toString()=="OK" ){
        QString number = jsonObject["number"].toString();
        if(jsonObject.contains(QString::fromStdString("results")))
        {
            QJsonValue jsonValueList = jsonObject.value(QString::fromStdString("results"));
            QJsonObject item = jsonValueList.toObject();
            if(item.contains(QString::fromStdString("nodeNameList"))){
                QJsonValue jsonValueList1 = item.value(QString::fromStdString("nodeNameList"));
                const QJsonArray &array = jsonValueList1.toArray();
                nodeName_list.clear();//清除原有数据

                for (int i = 0; i <array.size() ; ++i) {
                    qDebug()<<"array.at(i);=="<< array.at(i).toString();
                    //获取所有运行的 node节点的名称
                    nodeName_list.push_back(array.at(i).toString());
                }

                //sukai 获取所有运行的 node节点的名称发送给ui

               if(nodeName_listCallBack!=nullptr){
              nodeName_listCallBack(nodeName_list);
               }
            }


        }
    }else{
        qDebug()<<"error api_nodeName_List   error"<< "获取所有运行的node节点的名称失败！";

    }
}

// todo sukai 2022-01-22  接收授权码服务验证结果
void  IIMTDriver::api_registerServiceResult(QJsonObject &jsonObject){
    if(jsonObject["status"].toString()=="OK" ){
      QString registerServiceResult = jsonObject["result"].toString();
       //    接收授权码服务验证结果
       if(registerServiceResult_CallBack!=nullptr){
         registerServiceResult_CallBack(registerServiceResult);
       }

       qDebug()<<"接收slam授权码服务验证结果 "<<registerServiceResult;//
/**
接收授权码服务验证结果

   参数说明：
                           名称	         说明	                         	                 备注
                          success              授权码验证结果 成功
                          aborted              授权码验证结果 失败
                          emailSuccess         发送授权码到邮箱   成功
                          emailAborted         发送授权码到邮箱   失败
                          emailSuccessFromHttp 发送授权码到邮箱http通讯   失败
                          emailAbortedFromHttp 发送授权码到邮箱http通讯    失败
                          registerSuccess      邮箱中的授权码注册系统 成功
                          registerAborted      邮箱中的授权码注册系统 失败
                          againSuccess         授权码验证结果成功，不需要再次验证操作；
*/
    }
}



//=======================================================================================
//=======================================================================================

//在指定位置添加marker.
void  IIMTDriver::api_markers_insert_by_pose(QJsonObject &jsonObject) {
    if(jsonObject["status"].toString()=="OK" ){
        qDebug()<<"api_markers_insert_by_pose"<< "添加成功！";//// 点位名称：点位类型-楼层
    }else{
        qDebug()<<"error api_markers_insert_by_pose   error"<< "添加失败！";//// 点位名称：点位类型-楼层

    }
}
// 获取点位摘要信息
void  IIMTDriver::api_markers_query_brief(QJsonObject &jsonObject) {
    if(jsonObject["status"].toString()=="OK" ){
        if(jsonObject.contains(QString::fromStdString("results")))
        {
            QJsonValue jsonValueList = jsonObject.value(QString::fromStdString("results"));
            QJsonObject item = jsonValueList.toObject();
            qDebug()<<"item[meeting_room]=="<<item["meeting_room"].toString();// 点位名称：点位类型-楼层
            qDebug()<<"item[205_room]=="<<item["205_room"].toString();//// 点位名称：点位类型-楼层

            const QJsonArray &array = jsonValueList.toArray();
            for (int i = 0; i <array.size() ; ++i) {

                qDebug()<<"array.at(i);=="<< array.at(i);;//// 点位名称：点位类型-楼层


            }
        }
    }else if(jsonObject["status"].toString()=="UNKNOWN_ERROR"){

    }
}

//获取当前地图中的点位数量。
void  IIMTDriver::api_markers_count(QJsonObject &jsonObject){
    if(jsonObject["status"].toString()=="OK" ){
        if(jsonObject.contains(QString::fromStdString("results")))
        {
            QJsonValue jsonValueList = jsonObject.value(QString::fromStdString("results"));
            QJsonObject item = jsonValueList.toObject();
            qDebug()<<"item[count]=="<<item["count"].toString(); // 当前地图中点位的数量
        }
    }else if(jsonObject["status"].toString()=="UNKNOWN_ERROR"){

    }
}

// 获得机器人当前的全局状态
void  IIMTDriver::api_robot_status(QJsonObject &jsonObject){
    if(jsonObject["status"].toString()=="OK" ){
        if(jsonObject.contains(QString::fromStdString("results")))
        {
            QJsonValue jsonValueList = jsonObject.value(QString::fromStdString("results"));
            QJsonObject item = jsonValueList.toObject();
            qDebug()<<"item[move_target]=="<<item["move_target"].toString();// string  移动指令指定的目标点位名称;move_status表示当前机器人去move_target的执行状态。move_target表示移动指令指定的点位名称:充电桩；当以”location”调用移动接口时， 此字段值为空；当调用巡游接口时，此字段为当前正在前往的点位名称
            qDebug()<<"item[move_status]=="<<item["move_status"].toString();//string 移动指令的执行状态。详细解释见后边 。其取值及解释如下。idle:	表示机器人服务启动后尚未收到任何移动指令。running:表示机器人正在去往move_target,此时会拒绝接受新的移动指令。;succeeded:表示移动任务已经成功完成。   failed:表示移动任务失败了。 canceled:表示移动任务被取消了。
            qDebug()<<"item[running_status]=="<<item["running_status"].toString(); //string v0.7.12新增，移动任务的具体状态， 详细见后面解释； 底层实现是由通知触发, 在不能确保一定能收到通知的情况下, 可以以此字段作为判断条件。；；idle:机器人当前空闲,可以接受新的移动任务。[move_status:	idle/suceeded/failed/canceld];leave_charging_pile[move_status:running]正在离开充电桩。;dock_to_charging_pile[move_status:running] 正在自动停靠到充电桩上。;goto_lift[move_status:running]	正在去往电梯。;wait_lift_unlock [move_status:running]等待电梯解锁(当有多台机器人需要乘坐同一部电梯时会触发此状态。);;wait_lift_outside	[move_status:running]正在电梯外等候电梯。;enter_lift[move_status:running]	正在进入电梯(此时最好不要随便调用移动取消功能，以免流程出错。);avoid_lift[move_status:running] 进入电梯失败后正在避让电梯(此时最好不要随便调用移动取消功能，以免流程出错。);  take_lift	[move_status:running]正在乘坐电梯  (此时最好不要随便调用移动取消功能，以免流程出错);exit_lift[move_status:running]正在出电梯(此时最好不要随便调用移动取消功能，以免流程出错。);back_to_lift[move_status:running]出电梯失败正在回到电梯(此时最好不要随便调用移动取消功能，以免流程出错);running[move_status:running](其它非关键性状态)
            qDebug()<<"item[move_retry_times]=="<<item["move_retry_times"].toInt();//int 此次数每增加1，表示机器人进行了新一轮的路径重试；路径规划一次性成功此值默认为0

            qDebug()<<"item[charge_state]=="<<item["charge_state"].toBool();//bool, true->充电中状态。false->未充电状态。
            qDebug()<<"item[soft_estop_state]=="<<item["soft_estop_state"].toBool();// bool, 通过API接口设置的软急停状态, true->急停中，false->非急停中
            qDebug()<<"item[hard_estop_state]=="<<item["hard_estop_state"].toBool();// bool, 通过硬件急停按钮设置的硬急停状态, true->急停中，false->非急停中
            qDebug()<<"item[estop_state]=="<<item["estop_state"].toBool();//  bool, hard_estop_state || sofpt_estop_state, true->急停中，false->非急停中
            qDebug()<<"item[power_percent]=="<<item["power_percent"].toInt();//int 电量百分比，单位：%
            qDebug()<<"item[current_floor]=="<<item["current_floor"].toInt();//
            qDebug()<<"item[chargepile_id]=="<<item["chargepile_id"].toString();//v0.9.6新增。充电状态下表示当前正在充电的充电桩ID，非充电状态下返回“0”。注：此字段仅在部分产品中有效，其余返回“0”。
            qDebug()<<"item[error_code]=="<<item["error_code"].toString();//v0.7.7新增，16进制错误码，总共8个字节表示，非0表示机器人异常

            if(item.contains(QString::fromStdString("current_pose")))
            {

                QJsonValue jsonValueList_current_pose = item.value(QString::fromStdString("current_pose"));
                QJsonObject item_current_pose = jsonValueList_current_pose.toObject();
                qDebug()<<"item_current_pose[x]=="<<item_current_pose["x"].toDouble();//单位：m
               qDebug()<<"item_current_pose[y]=="<<item_current_pose["y"].toDouble();//单位：m
                qDebug()<<"item_current_pose[theta]=="<<item_current_pose["theta"].toDouble();//单位：rad
            }
        }
    }else if(jsonObject["status"].toString()=="UNKNOWN_ERROR"){

    }
}

// 接口 9 请求机器人实时数据
void  IIMTDriver::api_robot_data(QJsonObject &jsonObject){

   // "{\"results\":
   // {\"charge_state\":true,\"chargepile_id\":\"10106631\",\"current_floor\":2,\"current_pose\":
   // {\"theta\":1.1052,\"x\":68.3935,\"y\":34.639},
   // \"error_code\":\"00000000\",\"estop_state\":false,\"extraData\":\"\",\"hand_charge\":false,
   // \"hard_estop_state\":false,\"move_retry_times\":0,\"move_status\":\"succeeded\",\"move_target\":\"充电桩\",
   // \"power_percent\":100,\"running_status\":\"idle\",\"soft_estop_state\":false,\"target_floor\":0,\"task_id\":\"\"},
   // \"topic\":\"robot_status\",\"type\":\"callback\"}\n"

   // disinfect_msg::roboBasicState_msg msg;
    if(jsonObject.contains(QString::fromStdString("results")))
        {

            QJsonValue jsonValueList = jsonObject.value(QString::fromStdString("results"));
            QJsonObject item = jsonValueList.toObject();
//            qDebug()<<"item[move_target]=="<<item["move_target").toString();// string  移动指令指定的目标点位名称;move_status表示当前机器人去move_target的执行状态。move_target表示移动指令指定的点位名称:充电桩；当以”location”调用移动接口时， 此字段值为空；当调用巡游接口时，此字段为当前正在前往的点位名称
//            qDebug()<<"item[move_status]=="<<item["move_status").toString();//string 移动指令的执行状态。详细解释见后边 。其取值及解释如下。idle:	表示机器人服务启动后尚未收到任何移动指令。running:表示机器人正在去往move_target,此时会拒绝接受新的移动指令。;succeeded:表示移动任务已经成功完成。   failed:表示移动任务失败了。 canceled:表示移动任务被取消了。
//            qDebug()<<"item[running_status]=="<<item["running_status").toString(); //string v0.7.12新增，移动任务的具体状态， 详细见后面解释； 底层实现是由通知触发, 在不能确保一定能收到通知的情况下, 可以以此字段作为判断条件。；；idle:机器人当前空闲,可以接受新的移动任务。[move_status:	idle/suceeded/failed/canceld];leave_charging_pile[move_status:running]正在离开充电桩。;dock_to_charging_pile[move_status:running] 正在自动停靠到充电桩上。;goto_lift[move_status:running]	正在去往电梯。;wait_lift_unlock [move_status:running]等待电梯解锁(当有多台机器人需要乘坐同一部电梯时会触发此状态。);;wait_lift_outside	[move_status:running]正在电梯外等候电梯。;enter_lift[move_status:running]	正在进入电梯(此时最好不要随便调用移动取消功能，以免流程出错。);avoid_lift[move_status:running] 进入电梯失败后正在避让电梯(此时最好不要随便调用移动取消功能，以免流程出错。);  take_lift	[move_status:running]正在乘坐电梯  (此时最好不要随便调用移动取消功能，以免流程出错);exit_lift[move_status:running]正在出电梯(此时最好不要随便调用移动取消功能，以免流程出错。);back_to_lift[move_status:running]出电梯失败正在回到电梯(此时最好不要随便调用移动取消功能，以免流程出错);running[move_status:running](其它非关键性状态)
//            qDebug()<<"item[move_retry_times]=="<<item["move_retry_times").toInt();//int 此次数每增加1，表示机器人进行了新一轮的路径重试；路径规划一次性成功此值默认为0
//
//            qDebug()<<"item[charge_state]=="<<item["charge_state").toBool();//bool, true->充电中状态。false->未充电状态。
//            qDebug()<<"item[soft_estop_state]=="<<item["soft_estop_state").toBool();// bool, 通过API接口设置的软急停状态, true->急停中，false->非急停中
//            qDebug()<<"item[hard_estop_state]=="<<item["hard_estop_state").toBool();// bool, 通过硬件急停按钮设置的硬急停状态, true->急停中，false->非急停中
//            qDebug()<<"item[estop_state]=="<<item["estop_state").toBool();//  bool, hard_estop_state || sofpt_estop_state, true->急停中，false->非急停中
//            qDebug()<<"item[power_percent]=="<<item["power_percent").toInt();//int 电量百分比，单位：%
//            qDebug()<<"item[current_floor]=="<<item["current_floor").toInt();//当前楼层
//            qDebug()<<"item[chargepile_id]=="<<item["chargepile_id").toString();//v0.9.6新增。充电状态下表示当前正在充电的充电桩ID，非充电状态下返回“0”。注：此字段仅在部分产品中有效，其余返回“0”。
//            qDebug()<<"item[error_code]=="<<item["error_code").toString();//v0.7.7新增，16进制错误码，总共8个字节表示，非0表示机器人异常


//            msg.move_target=item["move_target").toString().toStdString();// string  移动指令指定的目标点位名称;move_status表示当前机器人去move_target的执行状态。move_target表示移动指令指定的点位名称:充电桩；当以”location”调用移动接口时， 此字段值为空；当调用巡游接口时，此字段为当前正在前往的点位名称
//            msg.move_status=item["move_status").toString().toStdString();//string 移动指令的执行状态。详细解释见后边 。其取值及解释如下。idle:	表示机器人服务启动后尚未收到任何移动指令。running:表示机器人正在去往move_target,此时会拒绝接受新的移动指令。;succeeded:表示移动任务已经成功完成。   failed:表示移动任务失败了。 canceled:表示移动任务被取消了。
//            msg.running_status=item["running_status").toString().toStdString();//string v0.7.12新增，移动任务的具体状态， 详细见后面解释； 底层实现是由通知触发, 在不能确保一定能收到通知的情况下, 可以以此字段作为判断条件。；；idle:机器人当前空闲,可以接受新的移动任务。[move_status:	idle/suceeded/failed/canceld];leave_charging_pile[move_status:running]正在离开充电桩。;dock_to_charging_pile[move_status:running] 正在自动停靠到充电桩上。;goto_lift[move_status:running]	正在去往电梯。;wait_lift_unlock [move_status:running]等待电梯解锁(当有多台机器人需要乘坐同一部电梯时会触发此状态。);;wait_lift_outside	[move_status:running]正在电梯外等候电梯。;enter_lift[move_status:running]	正在进入电梯(此时最好不要随便调用移动取消功能，以免流程出错。);avoid_lift[move_status:running] 进入电梯失败后正在避让电梯(此时最好不要随便调用移动取消功能，以免流程出错。);  take_lift	[move_status:running]正在乘坐电梯  (此时最好不要随便调用移动取消功能，以免流程出错);exit_lift[move_status:running]正在出电梯(此时最好不要随便调用移动取消功能，以免流程出错。);back_to_lift[move_status:running]出电梯失败正在回到电梯(此时最好不要随便调用移动取消功能，以免流程出错);running[move_status:running](其它非关键性状态)
//            msg.move_retry_times=item["move_retry_times").toInt();//int 此次数每增加1，表示机器人进行了新一轮的路径重试；路径规划一次性成功此值默认为0
//            if(item["charge_state").toBool()){//bool, true->充电中状态。false->未充电状态。
//                msg.is_charging="true";

//            }else{
//                msg.is_charging="false";
//            }
//            if(item["soft_estop_state").toBool()){// bool, 通过API接口设置的软急停状态, true->急停中，false->非急停中
//                msg.soft_estop_state="true";
//            }else{
//                msg.soft_estop_state="false";

//            }
//            if(item["hard_estop_state").toBool()){// bool, 通过硬件急停按钮设置的硬急停状态, true->急停中，false->非急停中
//                msg.hard_estop_state="true";
//            }else{
//                msg.hard_estop_state="false";

//            }
//            if(item["estop_state").toBool()){//  bool, hard_estop_state || sofpt_estop_state, true->急停中，false->非急停中
//                msg.estop_state="true";
//            }else{
//                msg.estop_state="false";

//            }
//            msg.battery_percentage=item["power_percent").toInt();//int 电量百分比，单位：%
//            msg.current_floor=item["current_floor").toInt();//当前楼层
//            msg.chargepile_id=item["chargepile_id").toString().toStdString();//v0.9.6新增。充电状态下表示当前正在充电的充电桩ID，非充电状态下返回“0”。注：此字段仅在部分产品中有效，其余返回“0”。
//            msg.error_code=item["error_code").toString().toStdString();//v0.7.7新增，16进制错误码，总共8个字节表示，非0表示机器人异常


//            if(item.contains(QString::fromStdString("current_pose")))
//            {

//                QJsonValue jsonValueList_current_pose = item.value(QString::fromStdString("current_pose"));
//                QJsonObject item_current_pose = jsonValueList_current_pose.toObject();
////                qDebug()<<"item_current_pose[x]=="<<item_current_pose["x").toDouble();//单位：m
////                qDebug()<<"item_current_pose[y]=="<<item_current_pose["y").toDouble();//单位：m
////                qDebug()<<"item_current_pose[theta]=="<<item_current_pose["theta").toDouble();//单位：rad

//                msg.x= to_string(item_current_pose["x").toDouble());
//                msg.y=to_string(item_current_pose["y").toDouble());
//                msg.theta=to_string(item_current_pose["theta").toDouble());

//            }


//            disinfect_msg::ac_client_callback data;
//            msg.header.frame_id='callBack_getRobotStatus';
//            msg.header.stamp=ros::Time::now();
//            msg.header.seq = 1;
//            if(msg.move_status=="idle"){//表示机器人服务启动后尚未收到任何移动指令
//                data.data="ActionStatusWaitingForStart";
//            }else if(msg.move_status=="running"){//表示机器人正在去往move_target,此时会拒绝接受新的移动指令
//                data.data="ActionStatusRunning";

//            }else if(msg.move_status=="succeeded"){//表示移动任务已经成功完成
//                data.data="ActionStatusFinished";

//            }else if(msg.move_status=="failed"){//表示移动任务失败了。
//                data.data="ActionStatusError";

//            }else if(msg.move_status=="canceled"){//表示移动任务被取消了。
//                data.data="ActionStatusStopped";

//            }
//            //发送小车当前的运行状态
//            getRobotStatusPub.publish(data);
//            //发送小车当前数据
//            robotBasicStatePub.publish(msg);
        }

}

//todo sukai 2021-11-05 字符串分割函数
std::vector<std::string> IIMTDriver::split(std::string pattern,std::string str)
{
    try {

        std::string::size_type pos;
        std::vector<std::string> result;
        str+=pattern; //扩展字符串以方便操作
        int  size=str.size();

        for ( int  i=0; i<size; i++)
        {
            pos=str.find(pattern,i);
            if (pos<size)
            {
                std::string s=str.substr(i,pos-i);
                result.push_back(s);
                i=pos+pattern.size()-1;
            }
        }
        return  result;

    }catch (std::exception e){
        qDebug() << "CarStartServuceClient::split 抛出异常！";
    }

}




//发送数据给plc，回调
void IIMTDriver::setSendPlcMsgCallBack(function<void(QString msg)> sendPlcMsgCallBack) {
    this->sendPlcMsgCallBack = sendPlcMsgCallBack;
}

void IIMTDriver::disConnectToRobot() {
    socket.disconnectFromHost();
}
//=============================================================================
//movej 加速度：a,速度v, 时间：t,交融半径： r,waitTime:执行当前这条指令前需要等待的时间 等待时间计算为当前服务器每次返回数据的频率的时间乘以waitTime，sendtypemsg:此脚本执行完成后需要发送给plc的消息,digitalStatus:执行该脚本时，当前对应的夹抓的状态
void
IIMTDriver::movej(double joints[6], double a, double v, double t, double r, int waitTime, QString sendtypemsg,int digitalStatus) {
    //添加到队列中
    addInstruction(MOVEJ, joints, a, v, t, r, waitTime, sendtypemsg,digitalStatus);

}

//movel 加速度：a,速度v, 时间：t,交融半径： r,waitTime:执行当前这条指令前需要等待的时间 等待时间计算为当前服务器每次返回数据的频率的时间乘以waitTime，sendtypemsg:此脚本执行完成后需要发送给plc的消息,digitalStatus:执行该脚本时，当前对应的夹抓的状态
void IIMTDriver::movel(double *pose, double a, double v, double t, double r, int waitTime, QString sendtypemsg,int digitalStatus) {
    //添加到队列中
    addInstruction(MOVEL, pose, a, v, t, r, waitTime, sendtypemsg,digitalStatus);

}

//movep 加速度：a,速度v, 时间：t,交融半径： r,waitTime:执行当前这条指令前需要等待的时间 等待时间计算为当前服务器每次返回数据的频率的时间乘以waitTime，sendtypemsg:此脚本执行完成后需要发送给plc的消息,digitalStatus:执行该脚本时，当前对应的夹抓的状态
void IIMTDriver::movep(double *pose, double a, double v, double t, double r, int waitTime, QString sendtypemsg,int digitalStatus) {
    //添加到队列中
    addInstruction(MOVEP, pose, a, v, t, r, waitTime, sendtypemsg,digitalStatus);

}

//movec 加速度：a,速度v, 时间：t,交融半径： r ,waitTime:执行当前这条指令前需要等待的时间 等待时间计算为当前服务器每次返回数据的频率的时间乘以waitTime，sendtypemsg:此脚本执行完成后需要发送给plc的消息,digitalStatus:执行该脚本时，当前对应的夹抓的状态
void IIMTDriver::movec(double *pose, double a, double v, double t, double r, int waitTime, QString sendtypemsg,int digitalStatus) {
    //添加到队列中
    addInstruction(MOVEC, pose, a, v, t, r, waitTime, sendtypemsg,digitalStatus);

}

//io digital ioInput 直接发送指令
void IIMTDriver::digital(int data[2]) {

    QString msg = script.loadIOScript(data[0], data[1]);
    //发送指令
    socket.write(msg.toUtf8());
}

//io digital ioInput 添加到队列中发送,sendtypemsg:此脚本执行完成后需要发送给plc的消息,digitalStatus:执行该脚本时，当前对应的夹抓的状态
void IIMTDriver::digitalToQueue(int data[2], int waitTime, QString sendtypemsg,int digitalStatus) {
    //添加到队列中发送
    addDigitalInstruction(DIGITAL, data[0], data[1], waitTime, sendtypemsg,digitalStatus);

}

//io digital ioInput 添加到队列中发送,sendtypemsg:此脚本执行完成后需要发送给plc的消息,digitalStatus:执行该脚本时，当前对应的夹抓的状态
void IIMTDriver::digitalToQueueNew(int num,int status, int waitTime, QString sendtypemsg,int digitalStatus) {
    //添加到队列中发送
    addDigitalInstruction(DIGITAL, num, status, waitTime, sendtypemsg,digitalStatus);

}

//  网络传输按大端模式进行数据转换
void IIMTDriver::parseData(QByteArray &data, IIMT_Data &iimtData) {
    //data.size():1108个字节， 139个数据
    char pdata[data.size()];
    memcpy(pdata, data.data(), data.size());
    char *p = pdata;
    reverseByte(p, 4);
    memcpy(&iimtData.MsgSize, pdata, 4);
    for (char *q = p + 4; q < p + data.size() - 8; q += 8) {
        //交换这8个数据
        reverseByte(q, 8);
    }
    memcpy(((char *) &iimtData) + 8, p + 4, data.size() - 4);
    //qDebug() << "IIMTDriver:== 80 ==iimtData.MsgSize=====: " << iimtData.MsgSize;
}

//添加运动指令 加速度：a,速度v, 时间：t,交融半径： r
//waitTime:（定时执行此脚本）执行当前这条脚本前需要等待的时间 等待时间计算为当前服务器每次返回数据的频率的时间乘以waitTime，sendtypemsg:此脚本执行完成后需要发送给plc的消息,digitalStatus:执行该脚本时，当前对应的夹抓的状态
void IIMTDriver::addInstruction(MOVETYPE movetype, double *data, double a, double v, double t, double r, int waitTime,
                                QString sendtypemsg,int digitalStatus) {
    //构建指令结构体
    Instruction instruction;
    instruction.movetype = movetype;
    instruction.sendtypemsg = sendtypemsg;
    instruction.digitalStatus=digitalStatus;
    //拷贝data后面6个数据到指令的data中
    memcpy(instruction.data, data, 6 * sizeof(double));
    instruction.a = a;
    instruction.v = v;
    instruction.t = t;
    instruction.r = r;
    if (waitTime > 0) {
        instruction.waitTime = waitTime;
    } else {
        instruction.waitTime = 1;
    }
    //添加到队列中
    instructionQueue.push(instruction);

}


//添加io指令 int num ：端口号, int status 状态
//waitTime:（定时执行此脚本）执行当前这条脚本前需要等待的时间 等待时间计算为当前服务器每次返回数据的频率的时间乘以waitTime，sendtypemsg:此脚本执行完成后需要发送给plc的消息,digitalStatus:执行该脚本时，当前对应的夹抓的状态
void
IIMTDriver::addDigitalInstruction(MOVETYPE movetype, int num, int status, int waitTime, QString sendtypemsg,int digitalStatus) {
    //构建指令结构体
    Instruction instruction;
    instruction.movetype = movetype;
    instruction.sendtypemsg = sendtypemsg;
    instruction.num = num;
    instruction.status = status;
    instruction.digitalStatus=digitalStatus;
    if (waitTime > 0) {
        instruction.waitTime = waitTime;
    } else {
        instruction.waitTime = 1;
    }

    //添加到队列中
    instructionQueue.push(instruction);
}


//是否执行下一条指令
void IIMTDriver::decideExcuteNextInstruction(IIMT_Data &iimtData) {




//sukai 2021-05-25    double resultVariance;
    //是否暂停
    if(isSTOPT)
        return;

    if (isFirst) {
        //如果第一次执行  直接执行
        excuteNextInstruction();
    } else {
        //不是第一次执行  判断是否和目标足够接近  isClose_resultVariance:目标精度 定义在/src/driver/IIMTDriver.h; resultVariance：获取计算返回的精度数据方便调试
       //iimtData:从服务器返回的数据， targetInstruction：目标数据
     //sukai 2021-05-25   bool b = isClose(targetInstruction, iimtData, isClose_resultVariance,resultVariance);
        bool b = isClose(targetInstruction, iimtData, isClose_resultVariance);
        if (b) {//到达目标点执行
            excuteNextInstructionAndsendPlcTypeMsg(iimtData);
        }
    }

}


//执行下一条指令及给plc发送指令
void IIMTDriver::excuteNextInstructionAndsendPlcTypeMsg(IIMT_Data &iimtData) {
    //获取当前脚本定时执行时间
    Instruction instruction;

    if(up_sendplctypemsg=="EMPTYPLC"){
        //判断是否有指令
        if (instructionQueue.empty()) {
            return;
        }
        //取出一条指令中的夹抓状态与定时器时间
        instruction = instructionQueue.front();
        //判断执行该脚本时对应的夹抓状态是否正确 iimtData:从服务器返回的数据， instruction：当前的数据
        if(instruction.digitalStatus!=iimtData.Digital_outputs&&instruction.digitalStatus!=-1)
            return;

        ex++;
        if (ex == instruction.waitTime) {//（获取定时执行时间）定时执行该条指令
            //执行下一条指令
            excuteNextInstruction();
            ex = 0;
        }
        //  qDebug()<<"========= 不向plc发送消息： EMPTYPLC ========执行：excuteNextInstruction======================== ";
    }else{
        //向plc发送消息
        sendPlcMsgCallBack(up_sendplctypemsg);
        //发送完改成 EMPTYPLC：不给plc发送任何消息
        up_sendplctypemsg = "EMPTYPLC";
    }

  //  qDebug() << "================ex=============" << (ex);
}


//执行下一条指令
void IIMTDriver::excuteNextInstruction() {
    //判断是否有指令
    if (instructionQueue.empty()) {
        return;
    }
    //取出一条执行
    Instruction &instruction = instructionQueue.front();
    QString msg;
    if (instruction.movetype == MOVEJ) {
        //执行指令 加速度：a,速度v, 时间：t,交融半径： r
        msg = script.loadMovejScript(instruction.data, instruction.a, instruction.v, instruction.t, instruction.r);
     //sukai 2021-05-25   qDebug() << "MOVEJ msg: " << msg;
    } else if (instruction.movetype == MOVEL) {
        msg = script.loadMovelScript(instruction.data, instruction.a, instruction.v, instruction.t, instruction.r);
        //sukai 2021-05-25     qDebug() << "MOVEL msg: " << msg;
    } else if (instruction.movetype == MOVEP) {

    } else if (instruction.movetype == MOVEC) {

    } else if (instruction.movetype == DIGITAL) {
        //添加到队列中
        msg = script.loadIOScript(instruction.num, instruction.status);
        //sukai 2021-05-25    qDebug() << "DIGITAL msg: " << msg;
    }

    // exTest++;
    //  if(exTest<=instruction.waitTime) {//执行这一条指令前时候休息会儿，让上一个指令结束后休息会执行这一条
    //发送指令
    socket.write(msg.toUtf8());
    //修改字段
    if (isFirst == true && instruction.movetype != DIGITAL) {
        isFirst = false;
    }
    //储存此执行的脚本结束后要给plc发送的消息（等脚本数据运行到目标位置也就是机械臂动作完成后，在下一条指令开始前发送这个消息）
    up_sendplctypemsg = instruction.sendtypemsg;
    //更新目标指令
    updateTargetInstruction(instruction);
    //删除队列中的这条指令
    instructionQueue.pop();
    //    exTest=0;
    //    qDebug()<<"==========模拟测试执行下发指令(完成)======exTest============="<<( exTest);
    // }

}

//更新目标指令
void IIMTDriver::updateTargetInstruction(Instruction &instruction) {
    if (instruction.movetype != DIGITAL) {//io不需要更新到目标值；这里主要是为了判断运动的目标点与当前点是否已经到达了
        targetInstruction.movetype = instruction.movetype;
        targetInstruction.sendtypemsg = instruction.sendtypemsg;
        memcpy(targetInstruction.data, instruction.data, 6 * sizeof(double));
        targetInstruction.a = instruction.a;
        targetInstruction.v = instruction.v;
        targetInstruction.t = instruction.t;
        targetInstruction.r = instruction.r;
    }


}


//删除Queue数据
void IIMTDriver::clearInstructionQueue() {
    while (!instructionQueue.empty()) {
        instructionQueue.pop();
    }
    isFirst = true;

}

//初始化参数
void IIMTDriver::initIImtDriver() {
   //删除Queue数据
    clearInstructionQueue();
    //是否是第一次
    isFirst = true;
    //是否暂停
    isSTOPT=false;
    //储存上一条脚本执行完成后需要给plc发送的消息，默认不发送消息：EMPTYPLC
//    up_sendplctypemsg=EMPTYPLC;
    //定时执行脚本的计数器
    ex = 0;
}

//==============================================测试 start========================================================================
//*******************************************************************************************************************************
//===============================================================================================================================


//使用网络助手做服务器 模拟测试执行下发指令 是否执行下一条指令 【没有机械臂的情况下使用，不能用于机械臂上】
// src/run/MainWindow.cpp  235行 IIMTDriverInstance->decideExcuteNextInstructionTest();打开注释启动该函数->测试完成记得把代码注释掉否则危险
void IIMTDriver::decideExcuteNextInstructionTest() {
    //判断是否有指令
    if (instructionQueue.empty()) {
        return;        if(nodeName_listCallBack!=nullptr){
            nodeName_listCallBack(nodeName_list);
             }
    }
    //取出一条判断等待时间
    Instruction instruction = instructionQueue.front();
    qDebug() << "==========模拟测试执行下发指令======instruction.waitTime=============" << (instruction.waitTime);

    if (isFirst) {
            //如果第一次执行  直接执行
            excuteNextInstruction();

    } else {
        excuteNextInstructionAndsendPlcTypeMsg(iimtData);
    }
    qDebug() << "==========模拟测试执行下发指令======exTest=============" << (ex);

}

//==============================================测试 end =========================================================================
//*******************************************************************************************************************************
//===============================================================================================================================


